分组查询的介绍


  • 使用 .annotate() 进行分组查询

  • 语法: 
    • .annotate(自定义key的名称=聚合函数方法名('表的类名')) -> 表的类名需要小写 -> 连表操作后进行分组
    • .annotate(自定义key的名称=聚合函数方法名('表的类名__字段名')) -> 连表操作后进行分组
    • .annotate(自定义key的名称=聚合函数方法名('字段名')) -> 对自身表进行分组

单表分组查询


  • 在单表分组查询中 .values('字段名') 里面填写这什么字段名,就以这个字段名进行分组

  • 查询每个部门的平均工资 -> 先将需要分组的部门字段数据查询出来

# models.py

# 员工表
class Staff(models.Model):
    name = models.CharField(max_length=10, verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    salary = models.IntegerField(verbose_name='薪资')
    address = models.CharField(max_length=10, verbose_name='地址')
    dep = models.CharField(max_length=10, verbose_name='部门')

# views.py

from app01.models import *
from django.db.models import Sum, Avg, Max, Min, Count

dep_data = Staff.objects.values('dep').annotate(avg=Avg('salary')).values('dep', 'avg')
for dep in dep_data:
    print('部门:{}, 薪资:{}'.format(dep['dep'], dep['avg']))

多表分组查询


多表分组查询,即: 连表查询

多表分组查询可以直接使用 .all() 方法

多表分组查询的执行顺序: 先进行连表操作,然后将分组后得到的结果放到 .all() 方法查询出来的每一个对象下  

1.多表分组查询的相关例子

  • 统计每一名老师所带的班的个数

from app01.models import *
from django.db.models import Sum, Avg, Max, Min, Count

teacher_data = Teacher.objects.all().annotate(class_num=Count('classes'))
for teacher in teacher_data:
    print('老师名称:{}, 班级个数:{}'.format(teacher.name, teacher.class_num))

  • 统计每个班级有多少名学生

from app01.models import *
from django.db.models import Sum, Avg, Max, Min, Count

classes_data = Classes.objects.all().annotate(student_num=Count('student'))
for classes in classes_data:
    print('班级名称:{}, 学生个数:{}'.format(classes.name, classes.student_num))

  • 查询班级人数大于2的班级

from app01.models import *
from django.db.models import Sum, Avg, Max, Min, Count

classes_data = Classes.objects.all().annotate(student_num=Count('student')).filter(student_num__gt=1)
for classes in classes_data:
    print('班级名称:{}, 学生个数:{}'.format(classes.name, classes.student_num))

  • 统计每个班级的平均年龄

from app01.models import *
from django.db.models import Sum, Avg, Max, Min, Count

classes_data = Classes.objects.all().annotate(student_avg=Avg('student__age')).values('name', 'student_avg')
print(classes_data)  # <QuerySet [{'student_avg': 21.5, 'name': '一班'}, {'student_avg': 23.0, 'name': '二班'}, {'student_avg': 25.0, 'name': '三班'}, {'student_avg': 30.0, 'name': '四班'}]>
for classes in classes_data:
    print('班级名称:{}, 学生平均年龄:{}'.format(classes['name'], classes['student_avg']))

  • 统计每个班级的平均年龄,然后以平均年龄进行倒序排序

from app01.models import *
from django.db.models import Sum, Avg, Max, Min, Count

classes_data = Classes.objects.all().annotate(student_avg=Avg('student__age')).order_by('-student_avg')
for classes in classes_data:
    print('班级名称:{}, 学生平均年龄:{}'.format(classes.name, classes.student_avg))